package com.jswlw.common.wx;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.jswlw.common.BaseException;
import com.jswlw.config.DefaultHttpClient;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import static com.jswlw.common.ResponseStatus.SYS_ERROR;
import static com.jswlw.common.wx.WeiXinConstant.WX_JSON2SESSION;

/**
 * @author 吴维斌 E-mail:wuweibin0817@163.com
 * @version 创建时间：${date} ${time}
 */
@Slf4j
@Component
public class WeiXinHelper {

    @Autowired
    DefaultHttpClient httpClient;

    @Value("${wx.app.appId}")
    String appId;

    @Value("${wx.app.appSecret}")
    String secret;

    String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";

    public String getAccessToken() {
        String url = TOKEN_URL + "&appid=" + appId + "&secret=" + secret;
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        try {
            Response response = httpClient.newCall(request).execute();
            JSONObject jsonObject = JSON.parseObject(response.body().string());
            log.info(jsonObject.toString());
            return (String) jsonObject.get("access_token");
        } catch (IOException e) {
            log.error("获取token失败", e);
        }
        return "";
    }

    public WxTokenResult getAccessToken(String code) {
        //构建请求参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", appId);
        paramMap.put("secret", secret);
        paramMap.put("code", code);

        paramMap.put("grant_type", "authorization_code");

        try {
            String url = WeiXinConstant.ACCESS_TOKEN_URL + "?" + mapToFormData(paramMap, false);
            Request request = new Request.Builder()
                    .url(url)
                    .get()
                    .build();
            //此处省略回调方法。
            Response response = httpClient.newCall(request).execute();

            JSONObject jsonObject = JSON.parseObject(response.body().string());
            log.warn("TOKEN信息:" + JSON.toJSONString(jsonObject));
            return JSON.toJavaObject(jsonObject, WxTokenResult.class);
        } catch (Exception e) {
            log.error("获取微信TOKEN信息失败", e);
            throw BaseException.of(SYS_ERROR.getCode(), "获取微信TOKEN信息失败");
        }
    }

    /**
     * 获取openId
     *
     * @param accessToken
     * @param openId
     * @return
     */
    public WeiXinUserInfo getWeiXinUserInfo(String accessToken, String openId) {
        accessToken = getAccessToken();
        //构建请求参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("access_token", accessToken);
        paramMap.put("openId", openId);
        paramMap.put("lang", "cn");
        log.info("paramMap:" + JSON.toJSONString(paramMap));
        try {
            String url = WeiXinConstant.USER_INFO_URL + "?" + mapToFormData(paramMap, false);
            Request request = new Request.Builder()
                    .url(url)
                    .get()
                    .build();
            Response response = httpClient.newCall(request).execute();
            String result = response.body().string();
            log.info("用户信息:" + result);
            WeiXinUserInfo userInfo = JSON.parseObject(result, WeiXinUserInfo.class);
            //返回结果处理
            return userInfo;
        } catch (Exception e) {
            log.error("获取微信信息失败", e);
            throw BaseException.of(SYS_ERROR.getCode(), "获取用户微信信息失败");
        }
    }

    public Code2SessionResult code2Session(String code) {
        String url = WX_JSON2SESSION + "&appid=" + appId + "&secret=" + secret + "&code=" + code;
        log.info(url);
        Request request = new Request.Builder()
                .url(url)
                .build();
        try {
            Response httpResponse = httpClient.newCall(request).execute();

            if (httpResponse.isSuccessful()) {

                String httpResult = httpResponse.body().string();
                log.info("请求返回结果:" + httpResult);
                Map httpResultMap = JSON.parseObject(httpResult);
                String openId = (String) httpResultMap.get("openid");
                if (StringUtils.isEmpty(openId)) {
                    BaseException.sneakyThrows(SYS_ERROR.getCode(), "获取OPENID失败");
                }

                return Code2SessionResult.builder()
                        .openId(openId)
                        .sessionKey((String) httpResultMap.get("session_key"))
                        .build();
            } else {
                BaseException.sneakyThrows(SYS_ERROR.getCode(), "获取OPENID失败");
            }
        } catch (IOException e) {
            log.error("获取openId失败", e);
            BaseException.sneakyThrows(SYS_ERROR.getCode(), "获取OPENID失败");
        }
        return null;
    }


    private static String mapToFormData(Map<String, String> map, boolean isURLEncoder) throws UnsupportedEncodingException {
        String formData = "";
        if (map != null && map.size() > 0) {
            formData = Joiner.on("&").withKeyValueSeparator("=").join(map);
            if (isURLEncoder) {
                formData = URLEncoder.encode(formData, "UTF-8");
            }
        }
        return formData;
    }
}
